// -*- C++ -*-
/***************************************************************************
 *
 * cwchar - C++ Standard library interface to the ANSI C header wchar.h
 *
 * $Id$
 *
 ***************************************************************************
 *
 * Copyright (c) 1994-2005 Quovadx,  Inc., acting through its  Rogue Wave
 * Software division. Licensed under the Apache License, Version 2.0 (the
 * "License");  you may  not use this file except  in compliance with the
 * License.    You    may   obtain   a   copy   of    the   License    at
 * http://www.apache.org/licenses/LICENSE-2.0.    Unless   required    by
 * applicable law  or agreed to  in writing,  software  distributed under
 * the License is distributed on an "AS IS" BASIS,  WITHOUT WARRANTIES OR
 * CONDITIONS OF  ANY KIND, either  express or implied.  See  the License
 * for the specific language governing permissions  and limitations under
 * the License.
 * 
 **************************************************************************/

#include <rw/_defs.h>

#ifndef _RWSTD_NO_PURE_C_HEADERS
#  include <ansi/_cwchar.h>
#else

#ifndef _RWSTD_NO_DEPRECATED_C_HEADERS

#ifndef _RWSTD_NAMESPACE_STD_OPEN
#define _RWSTD_NAMESPACE_STD_OPEN 17

_RWSTD_NAMESPACE (std) { 

#endif   // _RWSTD_NAMESPACE_STD_OPEN


#include _RWSTD_ANSI_C_WCHAR_H


#if _RWSTD_NAMESPACE_STD_OPEN == 17
#undef _RWSTD_NAMESPACE_STD_OPEN

}   // namespace std

#endif   // _RWSTD_NAMESPACE_STD_OPEN == 17

#else   // if defined (_RWSTD_NO_DEPRECATED_C_HEADERS)

#ifndef _RWSTD_CWCHAR_INCLUDED
#define _RWSTD_CWCHAR_INCLUDED

#include _RWSTD_ANSI_C_WCHAR_H
#include <rw/_mbstate.h>


// #define WEOF when not #defined (see also <cwctype>)
#if !defined WEOF
#  ifndef _RWSTD_NO_WINT_T
#    define WEOF _RWSTD_STATIC_CAST (_RWSTD_WINT_T, -1)
#  else
#    define WEOF (-1)
#  endif
#endif   // WEOF


#ifndef NULL
#  define NULL 0
#endif   // NULL


#if !defined (_RWSTD_NO_NAMESPACE) && !defined (_RWSTD_NO_HONOR_STD)


#ifndef WCHAR_MIN
#  define WCHAR_MIN   _RWSTD_WCHAR_MIN
#endif   // WCHAR_MIN

#ifndef WCHAR_MAX
#  define WCHAR_MAX   _RWSTD_WCHAR_MAX
#endif   // WCHAR_MAX


#if !defined (_RWSTD_NO_USING_LIBC_IN_STD)

// FIXME: when NOT introducing names into namespace std via using
// declarations but instead by declaring or defining them, all such
// names should be declared in the global namespace and only then
// introduced into namespace std by a using declaration for
// consistency with the others; otherwise #include <wchar.h> will
// bring in a mix of names, some in namespace std and others in
// the global namespace

namespace std {

#ifndef _RWSTD_NO_SIZE_T
    using ::size_t;
#elif defined (_RWSTD_SIZE_T)
    typedef _RWSTD_SIZE_T size_t;
#endif   // _RWSTD_NO_SIZE_T

#ifdef _RWSTD_NO_MBSTATE_T_IN_STD

using ::mbstate_t;

#endif   // _RWSTD_NO_MBSTATE_T_IN_STD

#ifndef _RWSTD_NO_WINT_T
    using ::wint_t;
#elif defined (_RWSTD_WINT_T)
    typedef _RWSTD_WINT_T wint_t;
#endif   // _RWSTD_NO_WINT_T

#ifndef _RWSTD_NO_STRUCT_TM_IN_WCHAR_H
    using ::tm;
#elif !defined (_RWSTD_NO_TM)

}   // namespace std

#include _RWSTD_ANSI_C_TIME_H

namespace std {

#endif   // NO_STRUCT_TM

#ifndef _RWSTD_NO_BTOWC
    using ::btowc;
#endif   // _RWSTD_NO_BTOWC

#ifndef _RWSTD_NO_FGETWC
    using ::fgetwc;
#endif   // _RWSTD_NO_FGETWC

#ifndef _RWSTD_NO_FGETWS
    using ::fgetws;
#endif   // _RWSTD_NO_FGETWS

#ifndef _RWSTD_NO_FPUTWC
    using ::fputwc;
#endif   // _RWSTD_NO_FPUTWC

#ifndef _RWSTD_NO_FPUTWS
    using ::fputws;
#endif   // _RWSTD_NO_FPUTWS

#ifndef _RWSTD_NO_FWIDE
    using ::fwide;
#endif   // _RWSTD_NO_FWIDE

#ifndef _RWSTD_NO_FWPRINTF
    using ::fwprintf;
#endif   // _RWSTD_NO_FWPRINTF

#ifndef _RWSTD_NO_FWSCANF
    using ::fwscanf;
#endif   // _RWSTD_NO_FWSCANF

#ifndef _RWSTD_NO_GETWC
    using ::getwc;
#endif   // _RWSTD_NO_GETWC

#ifndef _RWSTD_NO_PUTWC
    using ::putwc;
#endif   // _RWSTD_NO_PUTWC

#ifndef _RWSTD_NO_GETWCHAR
    using ::getwchar;
#endif   // _RWSTD_NO_GETWCHAR

#ifndef _RWSTD_NO_PUTWCHAR
    using ::putwchar;
#endif   // _RWSTD_NO_PUTWCHAR

#ifndef _RWSTD_NO_SWPRINTF
    using ::swprintf;
#endif   // _RWSTD_NO_SWPRINTF

#ifndef _RWSTD_NO_SWSCANF
    using ::swscanf;
#endif   // _RWSTD_NO_SWSCANF

#ifndef _RWSTD_NO_UNGETWC
    using ::ungetwc;
#endif   // _RWSTD_NO_UNGETWC

#ifndef _RWSTD_NO_VFWPRINTF
    using ::vfwprintf;
#endif   // _RWSTD_NO_VFWPRINTF

#ifndef _RWSTD_NO_VSWPRINTF
    using ::vswprintf;
#endif   // _RWSTD_NO_VSWPRINTF

#ifndef _RWSTD_NO_VWPRINTF
    using ::vwprintf;
#endif   // _RWSTD_NO_VWPRINTF

#ifndef _RWSTD_NO_WPRINTF
    using ::wprintf;
#endif   // _RWSTD_NO_WPRINTF

#ifndef _RWSTD_NO_WSCANF
    using ::wscanf;
#endif   // _RWSTD_NO_WSCANF

#ifndef _RWSTD_NO_MBRLEN
    using ::mbrlen;
#else // defined _RWSTD_NO_MBRLEN 
#  ifndef _RWSTD_NO_MBRLEN_IN_LIBC
    extern "C" size_t mbrlen (const char*, size_t, mbstate_t*);
#  endif // _RWSTD_NO_MBRLEN_IN_LIBC
#endif   // _RWSTD_NO_MBRLEN

#ifndef _RWSTD_NO_MBRTOWC
    using ::mbrtowc;
#else // defined _RWSTD_NO_MBRTOWC
#  ifndef _RWSTD_NO_MBRTOWC_IN_LIBC
    extern "C" size_t mbrtowc (wchar_t*, const char*, size_t, mbstate_t*);
#  endif // _RWSTD_NO_MBRTOWC_IN_LIBC
#endif   // _RWSTD_MBRTOWC

#ifndef _RWSTD_NO_MBSINIT
    using ::mbsinit;
#elif !defined (_RWSTD_NO_MBSINIT_IN_LIBC)
    extern "C" int mbsinit (const mbstate_t*);
#endif   // !_RWSTD_NO_MBSINIT_IN_LIBC

#ifndef _RWSTD_NO_MBSRTOWCS
    using ::mbsrtowcs;
#else // defined _RWSTD_NO_MBSRTOWCS
#  ifndef _RWSTD_NO_MBSRTOWCS_IN_LIBC
    extern "C" size_t mbsrtowcs (wchar_t*, const char**, size_t, mbstate_t*);
#  endif  // _RWSTD_NO_MBSRTOWCS_IN_LIBC
#endif    // _RWSTD_NO_MBSRTOWCS

#ifndef _RWSTD_NO_WCRTOMB
    using ::wcrtomb;
#else // defined _RWSTD_NO_WCRTOMB
#  ifndef _RWSTD_NO_WCRTOMB_IN_LIBC
    extern "C" size_t wcrtomb (char*, wchar_t, mbstate_t*);
#  endif // _RWSTD_NO_WCRTOMB_IN_LIBC
#endif   // _RWSTD_NO_WCRTOMB

#ifndef _RWSTD_NO_WCSCAT
    using ::wcscat;
#elif !defined (_RWSTD_NO_WCSCAT_IN_LIBC)
    extern "C" wchar_t* wcscat (wchar_t*, const wchar_t*);
#else   // if defined (_RWSTD_NO_WCSCAT)

    inline wchar_t* wcscat (wchar_t *__dst, const wchar_t *__src)
    {
        wchar_t *__s = __dst;
        for (; *__s; ++__s);
        while ((*__s++ = *__src++));
        return __dst;
    }

#endif   // _RWSTD_NO_WCSCAT

#undef _RWSTD_NO_WCSCAT


#ifndef _RWSTD_NO_WCSCHR
    using ::wcschr;
#elif !defined (_RWSTD_NO_WCSCHR_IN_LIBC)

    extern "C" wchar_t* wcschr (wchar_t*, wchar_t);


    inline const wchar_t* wcschr (const wchar_t *__s, wchar_t __c)
    {
        return wcschr (_RWSTD_CONST_CAST (wchar_t*, __s), __c);
    }
    
#else   // if defined (_RWSTD_NO_WCSCHR)

    inline const wchar_t* wcschr (const wchar_t *__s, wchar_t __c)
    {
        do {
            if (*__s == __c)
                return __s;
        } while (*__s);
        return 0;
    }

    inline wchar_t* wcschr (wchar_t *__s, wchar_t __c)
    {
        return _RWSTD_CONST_CAST (wchar_t*,
                                  (wcschr ((const wchar_t*)__s, __c)));
    }

#endif   // _RWSTD_NO_WCSCHR

#undef _RWSTD_NO_WCSCHR


#ifndef _RWSTD_NO_WCSCMP
    using ::wcscmp;
#else   // if defined (_RWSTD_NO_WCSCMP)
#endif   // _RWSTD_NO_WCSCMP

#ifndef _RWSTD_NO_WCSCOLL
    using ::wcscoll;
#else   // if defined (_RWSTD_NO_WCSCOLL)
#endif   // _RWSTD_NO_WCSCOLL

#ifndef _RWSTD_NO_WCSCPY
    using ::wcscpy;
#else   // if defined (_RWSTD_NO_WCSCPY)

    inline wchar_t* wcscpy (wchar_t *__dst, const wchar_t *__src)
    {
        for (wchar_t *__s = __dst; (*__s++ = *__src++); );
        return __dst;
    }

#endif   // _RWSTD_NO_WCSCPY

#undef _RWSTD_NO_WCSCPY


#ifndef _RWSTD_NO_WCSCSPN
    using ::wcscspn;
#else   // if defined (_RWSTD_NO_WCSCSPN)

    inline size_t wcscspn (const wchar_t *__s1, const wchar_t *__s2)
    {
        const wchar_t *__s = __s1;
        for (; *__s; ++__s) {
            for (const wchar_t *__ss = __s2; *__ss; ++__ss)
                if (*__ss == *__s)
                    return __s - __s1;
        }
        return __s - __s1;
    }

#endif   // _RWSTD_NO_WCSCSPN

#ifndef _RWSTD_NO_WCSFTIME
    using ::wcsftime;
#endif   // _RWSTD_NO_WCSFTIME


#ifndef _RWSTD_NO_WCSLEN
    using ::wcslen;
#elif !defined (_RWSTD_NO_WCSLEN_IN_LIBC)
    extern "C" size_t wcslen (const wchar_t*);
#else   // defined (_RWSTD_NO_WCSLEN)

    extern "C" {

    inline size_t wcslen (const wchar_t* __s)
    {
        const wchar_t *__begin = __s;
        while (*__s)
            ++__s;
        return __s - __begin;
    }

    }

#endif   // _RWSTD_NO_WCSLEN

#undef _RWSTD_NO_WCSLEN


#ifndef _RWSTD_NO_WCSNCAT
    using ::wcsncat;
#else   // if defined (_RWSTD_NO_WCSNCAT)

    inline wchar_t* wcsncat (wchar_t *__dst, const wchar_t *__src, size_t __n)
    {
        wchar_t *__s = __dst;
        for (; *__s; ++__s);
        while (__n--)
            if (!(*__s++ = *__src++))
                return __dst;
        *__s = 0;
        return __dst;
    }

#endif   // _RWSTD_NO_WCSNCAT

#ifndef _RWSTD_NO_WCSNCMP
    using ::wcsncmp;
#elif !defined (_RWSTD_NO_WCSNCMP_IN_LIBC)
    extern "C" int wcsncmp (const wchar_t*, const wchar_t*, size_t);
#else   // if defined (_RWSTD_NO_WCSNCMP)

    inline int wcsncmp (const wchar_t *__s1, const wchar_t *__s2, size_t __n)
    {
        if (!__n)
            return 0;
        for (; --__n && *__s1 && *__s1 == *__s2; ++__s1, ++__s2);
        return int (*__s1 - *__s2);
    }

#endif   // _RWSTD_NO_WCSNCMP

#undef _RWSTD_NO_WCSNCMP


#ifndef _RWSTD_NO_WCSNCPY
    using ::wcsncpy;
#elif !defined (_RWSTD_NO_WCSNCPY_IN_LIBC)

    extern "C" wchar_t* wcsncpy (wchar_t*, const wchar_t*, size_t);

#else   // if defined (_RWSTD_NO_WCSNCPY)

    inline wchar_t* wcsncpy (wchar_t *__dst, const wchar_t *__src, size_t __n)
    {
        wchar_t *__s = __dst;
        for (; __n && (*__s++ = *__src++); --__n);
        while (__n--)
            *__s = 0;
        return __dst;
    }

#endif   // _RWSTD_NO_WCSNCPY

#undef _RWSTD_NO_WCSNCPY


#ifndef _RWSTD_NO_WCSPBRK
    using ::wcspbrk;
#elif !defined (_RWSTD_NO_WCSPBRK_IN_LIBC)

    extern "C" wchar_t* wcspbrk (wchar_t*, const wchar_t*);

    inline const wchar_t* wcspbrk (const wchar_t *__s1, const wchar_t *__s2)
    {
        return wcspbrk (_RWSTD_CONST_CAST (wchar_t*, __s1), __s2);
    }

#endif   // _RWSTD_NO_WCSPBRK

#undef _RWSTD_NO_WCSPBRK


#ifndef _RWSTD_NO_WCSRCHR
    using ::wcsrchr;
#elif !defined (_RWSTD_NO_WCSRCHR_IN_LIBC)

    extern "C" const wchar_t* wcsrchr (const wchar_t*, wchar_t);

#else   // if defined (_RWSTD_NO_WCSRCHR)

    inline const wchar_t* wcsrchr (const wchar_t *__s, wchar_t __c)
    {
        const wchar_t *__ss = __s;
        while (*__ss++);
        while (--__ss != __s && *__ss != __c);
        return *__ss == __c ? __ss : 0;
    }

    inline wchar_t* wcsrchr (wchar_t *__s, wchar_t __c)
    {
        return _RWSTD_CONST_CAST (wchar_t*,
                                  (wcsrchr ((const wchar_t*)__s, __c)));
    }

#endif   // _RWSTD_NO_WCSRCHR

#undef _RWSTD_NO_WCSRCHR


#ifndef _RWSTD_NO_WCSRTOMBS
    using ::wcsrtombs;
#else // defined _RWSTD_NO_WCSRTOMBS
#  ifndef _RWSTD_NO_WCSRTOMBS_IN_LIBC
    extern "C" size_t wcsrtombs (char*, const wchar_t**, size_t, mbstate_t*);
#  endif
#endif   // _RWSTD_NO_WCSRTOMBS

#ifndef _RWSTD_NO_WCSSPN
    using ::wcsspn;
#else
    
    inline size_t wcsspn (const wchar_t *__s1, const wchar_t *__s2)
    {
        const wchar_t *__s = __s1;
        for (; *__s; ++__s) {
            for (const wchar_t *__ss = __s2; *__ss != *__s; ++__ss)
                if (!*__ss)
                    return __s - __s1;
        }
        return __s - __s1;
    }

#endif   // _RWSTD_NO_WCSSPN

#ifndef _RWSTD_NO_WCSSTR
    using ::wcsstr;
#else   // if defined (_RWSTD_NO_WCSSTR)

#  ifdef __hpux

    inline const wchar_t* wcsstr (const wchar_t *__s1, const wchar_t *__s2)
    {
        return wcswcs (__s1, __s2);
    }

    inline wchar_t* wcsstr (wchar_t *__s1, const wchar_t *__s2)
    {
        return wcswcs (__s1, __s2);
    }

#  endif   // __hpux

#endif   // _RWSTD_NO_WCSSTR

#ifndef _RWSTD_NO_WCSTOD
    using ::wcstod;
#endif   // _RWSTD_NO_WCSTOD

#ifndef _RWSTD_NO_WCSTOK
    using ::wcstok;
#endif   // _RWSTD_NO_WCSTOK

#ifndef _RWSTD_NO_WCSTOL
    using ::wcstol;
#endif   // _RWSTD_NO_WCSTOL

#ifndef _RWSTD_NO_WCSTOUL
    using ::wcstoul;
#endif   // _RWSTD_NO_WCSTOUL

#ifndef _RWSTD_NO_WCSXFRM
    using ::wcsxfrm;
#endif   // _RWSTD_NO_WCSXFRM

#ifndef _RWSTD_NO_WCTOB
    using ::wctob;
#elif !defined (_RWSTD_NO_WCTOB_IN_LIBC)
    extern "C" int wctob (wint_t);

#  undef _RWSTD_NO_WCTOB
#endif   // _RWSTD_NO_WCTOB


#ifndef _RWSTD_NO_WMEMCHR
    using ::wmemchr;
#else

}   // namespace std

inline const wchar_t* wmemchr (const wchar_t* __s, wchar_t __c, size_t __n)
{
    for (; __n ; --__n, ++__s)
        if (*__s == __c)
            return __s;
    return 0;
}

inline wchar_t* wmemchr (wchar_t* __s, wchar_t __c, size_t __n)
{
    return _RWSTD_CONST_CAST (wchar_t*,
                              wmemchr ((const wchar_t*)__s, __c, __n));
}

namespace std {

    using ::wmemchr;

#endif   // _RWSTD_NO_WMEMCHR

#undef _RWSTD_NO_WMEMCHR


#ifndef _RWSTD_NO_WMEMCMP
    using ::wmemcmp;
#elif !defined (_RWSTD_NO_WMEMCMP_IN_LIBC)

}   // namespace std

extern "C" int wmemcmp (const void*, const void*, size_t);

namespace std {

    using ::wmemcmp;

#else   // if _RWSTD_NO_WMEMCMP && _RWSTD_NO_WMEMCMP_IN_LIBC

}   // namespace std

extern "C" {

    inline int wmemcmp (const void *__s1, const void *__s2, size_t __n)
    {
        const wchar_t *__ss1 = _RWSTD_REINTERPRET_CAST (const wchar_t*, __s1);
        const wchar_t *__ss2 = _RWSTD_REINTERPRET_CAST (const wchar_t*, __s2);

        for (; __n; --__n, ++__ss1, ++__ss2)
            if (*__ss1 != *__ss2)
                return *__ss1 - *__ss2;
        return 0;
    }

}

namespace std {

    using ::wmemcmp;

#endif   // _RWSTD_NO_WMEMCMP

#undef _RWSTD_NO_WMEMCMP


#ifndef _RWSTD_NO_WMEMCPY
    using ::wmemcpy;
#elif !defined (_RWSTD_NO_WMEMCPY_IN_LIBC)
    extern "C" wchar_t* wmemcpy (wchar_t*, const wchar_t*, size_t);
#else   // if _RWSTD_NO_WMEMCPY && _RWSTD_NO_WMEMCPY_IN_LIBC

    extern "C" {

    inline wchar_t* wmemcpy (wchar_t *__dst, const wchar_t *__src, size_t __n)
    {
        for (wchar_t *__d = __dst; __n--; ++__d, ++__src)
            *__d = *__src;

        return __dst;
    }

    }

#endif   // _RWSTD_NO_WMEMCPY

#undef _RWSTD_NO_WMEMCPY


#ifndef _RWSTD_NO_WMEMMOVE
    using ::wmemmove;
#elif !defined (_RWSTD_NO_WMEMMOVE_IN_LIBC)
    extern "C" wchar_t* wmemmove (wchar_t*, const wchar_t*, size_t);
#else   // if _RWSTD_NO_WMEMMOVE && _RWSTD_NO_WMEMMOVE_IN_LIBC

    extern "C" {

    inline wchar_t*
    wmemmove (wchar_t *__dst, const wchar_t *__src, size_t __n)
    {
        if (__dst < __src || __dst >= __src + __n)
            wmemcpy (__dst, __src, __n);
        else {
            // regions overlap
            __dst += __n;
            __src += __n;
            while (__n--)
                *--__dst = *--__src;
        }
        return __dst;
    }

    }

#endif   // _RWSTD_NO_WMEMMOVE

#undef _RWSTD_NO_WMEMMOVE


#ifndef _RWSTD_NO_WMEMSET
    using ::wmemset;
#elif !defined (_RWSTD_NO_WMEMSET_IN_LIBC)
    extern "C" wchar_t* wmemset (wchar_t*, wchar_t, size_t);
#else   // if _RWSTD_NO_WMEMSET && _RWSTD_NO_WMEMSET_IN_LIBC

    extern "C" {

    inline wchar_t* wmemset (wchar_t* __s, wchar_t __c, size_t __n)
    {
        while (__n)
            __s [--__n] = __c;
        return __s;
    }

    }

#endif   // _RWSTD_NO_WMEMSET

#undef _RWSTD_NO_WMEMSET

}   // std

#endif   // !_RWSTD_NO_USING_LIBC_IN_STD

#endif   // !_RWSTD_NO_NAMESPACE && !_RWSTD_NO_HONOR_STD

#endif   // _RWSTD_CWCHAR_INCLUDED

#endif   // _RWSTD_NO_DEPRECATED_C_HEADERS

#endif   // _RWSTD_NO_PURE_C_HEADERS
